﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Win32;
using System.Windows.Forms;
using System.Diagnostics;

namespace eBook.WinApp
{
  public delegate void ClipboardEventHandler(object sender, ClipboardEventArgs e);

  public class ClipboardEventArgs : EventArgs
  {
    public string Text { get; set; }  
  }

  public class ClipboardHook
  {
    private ClipboardEventHandler _onClipboardText;
    public event ClipboardEventHandler OnClipboardText 
    { 
      add {_onClipboardText += value;}
      remove { _onClipboardText -= value; }
    }

    private IntPtr _clipboardViewerNext;
    
    public void RegisterClipboardViewer(IntPtr handle)
    {
      _clipboardViewerNext = User32.SetClipboardViewer(handle);
    }

    public void UnregisterClipboardViewer(IntPtr handle)
    {
      User32.ChangeClipboardChain(handle, _clipboardViewerNext);
    }

    private string GetClipboardData()
    {
      string clpContent = string.Empty;
      IDataObject iData = Clipboard.GetDataObject();
      if (iData.GetDataPresent(DataFormats.Text))
      {
        clpContent = (string) iData.GetData(DataFormats.Text);
        if (_onClipboardText != null)
        {
          _onClipboardText(this, new ClipboardEventArgs { Text = clpContent });
        }
      }

      return clpContent;
    }

    public bool HandleClipboardMessage(Message m)
    {
      bool handled = true;
      switch ((Msgs)m.Msg)
      {
        // The WM_DRAWCLIPBOARD message is sent to the first window in the clipboard viewer chain when the content of the 
        // clipboard changes. This enables a clipboard viewer window to display the new content of the clipboard.         
        case Msgs.WM_DRAWCLIPBOARD:
          Debug.WriteLine("WindowProc DRAWCLIPBOARD: " + m.Msg, "WndProc");
          // Each window that receives the WM_DRAWCLIPBOARD message must call the SendMessage function to pass the message 
          // on to the next window in the clipboard viewer chain.
          User32.SendMessage(_clipboardViewerNext, m.Msg, m.WParam, m.LParam);
          string s = this.GetClipboardData();          
          break;

        // The WM_CHANGECBCHAIN message is sent to the first window in the clipboard viewer chain when a window is being 
        // removed from the chain. 
        case Msgs.WM_CHANGECBCHAIN:
          Debug.WriteLine("WM_CHANGECBCHAIN: lParam: " + m.LParam, "WndProc");

          // When a clipboard viewer window receives the WM_CHANGECBCHAIN message, it should call the SendMessage function to pass the message to the 
          // next window in the chain, unless the next window is the window being removed. In this case, the clipboard viewer should save 
          // the handle specified by the lParam parameter as the next window in the chain. 

          // wParam is the Handle to the window being removed from the clipboard viewer chain lParam is the Handle to the next window in the chain 
          // following the window being removed. 
          if (m.WParam == _clipboardViewerNext)
          {
            // If wParam is the next clipboard viewer then it is being removed so update pointer to the next
            // window in the clipboard chain
            _clipboardViewerNext = m.LParam;
          }
          else
          {
            User32.SendMessage(_clipboardViewerNext, m.Msg, m.WParam, m.LParam);
          }
          break;

        default:
          handled = false;
          break;
      }

      return handled;
    } 

  }
}
